package yxy.game.pm2.module.guard;

import java.util.Collection;

import org.joda.time.DateTime;

import yxy.cherry.battle.module.record.FighterSide;
import yxy.cherry.battle.module.record.result.StatisticFighter;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.packagedata;
import yxy.cherry.game.base.message.MessageEmitterHandler;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format.FormatType;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.module.RedisLock;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.GuardMessage;
import yxy.game.pm2.message.GuardMessage.GuardChanllengeResetResponse.Builder;
import yxy.game.pm2.message.PlayerMessage;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.BattleHandle;
import yxy.game.pm2.module.battle.BattleModule;
import yxy.game.pm2.module.battle.BattleType;
import yxy.game.pm2.module.battle.TeamModule;
import yxy.game.pm2.module.guard.GuardModule.GuardState;
import yxy.game.pm2.module.guard.GuardPlayerModule.GuardOperate;
import yxy.game.pm2.module.player.PlayerHandle;
import yxy.game.pm2.module.stat.StatHandle;

public class GuardHandle {

	private String code() {
		return BattleType.GUARD.name();
	}

	// 活动信息
	public void info(String playerCode, GuardMessage.GuardUIResponse.Builder response) {
		subscriber(playerCode);

		GuardModule guardModule = GuardModule.get(playerCode);

		GuardState state = guardModule.getState();
		DateTime stateTime = guardModule.getStateTimes().get(state);
		response.setState(state.getValue());
		response.setEndtime(stateTime.getMillis());

		switch (state) {
		default:
		case GS_0_选将:
			break;
		case GS_1_守将: {
			GuardMessage.GuardStateInfo.Builder stateInfo = GuardMessage.GuardStateInfo.newBuilder();
			for (Guard guard : guardModule.getGuards()) {
				GuardMessage.GuardInfo.Builder guardInfo = GuardMessage.GuardInfo.newBuilder();
				guardInfo.setPlayerInfo(new PlayerHandle().playerSimpleInfo(guard.getPlayerCode()));
				guardInfo.setAlive(guard.alive());
				stateInfo.addGuards(guardInfo);
			}

			response.setInfo(stateInfo);
		}
			break;
		case GS_2_攻城: {
			GuardMessage.GuardStateInfo.Builder stateInfo = GuardMessage.GuardStateInfo.newBuilder();

			boolean isGuard = false;
			for (Guard guard : guardModule.getGuards()) {
				GuardMessage.GuardInfo.Builder guardInfo = GuardMessage.GuardInfo.newBuilder();
				guardInfo.setPlayerInfo(new PlayerHandle().playerSimpleInfo(guard.getPlayerCode()));
				guardInfo.setAlive(guard.alive());
				stateInfo.addGuards(guardInfo);
				if (playerCode.equals(guard.getPlayerCode())) {
					isGuard = true;
				}
			}
			int guardIndex = guardModule.current();
			Guard currentGuard = guardModule.getGuards().get(guardIndex);
			stateInfo.setHp(currentGuard.hp());
			stateInfo.setBeing(guardModule.current());
			stateInfo.setInspire(guardModule.inspireValue());

			// 伤害排名
			RankGuard rankGuard = RankGuard.getRank(playerCode, guardIndex);

			Collection<RankEntry> attack = rankGuard.top(5);
			int rank = 0;
			for (RankEntry entry : attack) {
				GuardMessage.RankGuard.Builder builder = GuardMessage.RankGuard.newBuilder();
				builder.setRank(++rank);
				builder.setPlayerInfo(playerMiniInfo(entry.getKey()));
				builder.setDamage(entry.getValue());
				stateInfo.addRank(builder);
			}
			// 守
			if (!isGuard) {
				int playerRank = 0;
				int score = 0;
				RankEntry entry = rankGuard.get(playerCode);
				if (entry != null) {
					playerRank = rankGuard.rank(playerCode);
					score = entry.getValue().intValue();
				}
				GuardMessage.RankGuard.Builder builder = GuardMessage.RankGuard.newBuilder();
				builder.setRank(playerRank);
				builder.setPlayerInfo(playerMiniInfo(playerCode));
				builder.setDamage(score);
				stateInfo.setMy(builder);
			}
			response.setInfo(stateInfo);

			// 操作CD
			GuardPlayerModule guardPlayerModule = GuardPlayerModule.get(playerCode);
			response.addAllOperCd(guardPlayerModule.operationList());
		}
			break;
		case GS_3_守胜:
		case GS_4_攻胜: {
			GuardMessage.GuardStateInfo.Builder stateInfo = GuardMessage.GuardStateInfo.newBuilder();
			boolean isGuard = false;
			for (Guard guard : guardModule.getGuards()) {
				GuardMessage.GuardInfo.Builder guardInfo = GuardMessage.GuardInfo.newBuilder();
				guardInfo.setPlayerInfo(new PlayerHandle().playerSimpleInfo(guard.getPlayerCode()));
				guardInfo.setAlive(guard.alive());
				stateInfo.addGuards(guardInfo);
				if (playerCode.equals(guard.getPlayerCode())) {
					isGuard = true;
				}
			}
			response.setInfo(stateInfo);

			// 领奖
			GuardPlayerModule guardPlayerModule = GuardPlayerModule.get(playerCode);
			boolean canReward = false;
			if (state.equals(GuardState.GS_3_守胜)) {
				canReward = isGuard && !guardPlayerModule.isRewarded();
			} else {
				canReward = !isGuard && !guardPlayerModule.isRewarded() && guardModule.isOffense(playerCode);
			}
			response.setReward(canReward);
		}
			break;
		}
	}

	/** 处理战斗 */
	public Result battleResponseExecute(String playerCode, GuardMessage.GuardChanllengeResponse.Builder response) throws Exception {
		GuardModule guardModule = GuardModule.get(playerCode);

		// cd
		GuardOperate operate = GuardOperate.OP_攻城;
		GuardPlayerModule guardPlayerModule = GuardPlayerModule.get(playerCode);
		{
			DateTime now = DateTime.now();
			DateTime cd = guardPlayerModule.getCoolDown().get(operate);

			System.err.println("now::	" + now);
			System.err.println("cd ::	" + cd);
			boolean isGuard = guardModule.guard(playerCode);
			if (isGuard) {
				return Result.GuardCantOperate;// 不能做这个操作
			}
			int cdtime = GuardModule.data().getAssaultcd();
			DateTime cdupper = now.plusSeconds(GuardModule.data().getAssaultcdmax());
			if (cd.plusSeconds(cdtime).isAfter(cdupper)) {
				return Result.GuardCantOperate;// 不能做这个操作
			}
			if (cd.isBefore(now)) {
				guardPlayerModule.getCoolDown().put(operate, now.plusSeconds(cdtime));
			} else {
				guardPlayerModule.getCoolDown().put(operate, cd.plusSeconds(cdtime));
			}

			guardPlayerModule.set();
		}

		int guardIndex = guardModule.current();
		Guard currentGuard = guardModule.getGuards().get(guardIndex);

		BattleHandle battleHandle = new BattleHandle();

		BattleModule battleModule = BattleModule.create(playerCode);
		battleModule.setType(BattleType.GUARD);
		battleModule.setCode(code());

		// 玩家的team
		TeamModule teamA = battleHandle.teamPlayer(playerCode, FormatType.普通);
		battleModule.setTeamA(teamA);

		// Boss的team
		TeamModule teamB = currentGuard.team();
		battleModule.setTeamB(teamB);

		//todo 修改登录时间，3天后自动清除缓存
		StatHandle.stat_用户登录状态更新(teamB.getPlayerCode());


		BattleMessage.BattleExecuteResponse res = new BattleHandle().battleResponseExecute(battleModule //
				, 20, false, null);

		// 计算伤害
		long damage = 0;
		for (StatisticFighter fighter : battleModule.getStatistics()) {
			if (fighter.getPos().getSide().equals(FighterSide.RIGHT)) {
				damage += fighter.getHut();
				for (GuardHero hero : currentGuard.getHeros()) {
					if (hero.getPos().equals(fighter.getPos().getPosition())) {
						hero.setResidual(hero.getResidual() - fighter.getHut());
					}
				}
			}
		}
		if (damage > 0) {
			RankGuard rank = RankGuard.getRank(playerCode, guardIndex);
			rank.addAndSet(playerCode, damage);
			guardModule.addOffense(playerCode);
			if (!currentGuard.alive()) {
				// 守将阵亡
				rank.reward();
				// 活动结束
				if (guardIndex >= 2) {
					guardModule.updateState(GuardState.GS_4_攻胜);
				}
			}
		}

		guardModule.set();

		// 封装消息
		response.setBattleResp(res);// 录像
		response.setBattleResult(battleModule.getBattleResult().getNumber());// 战果
		response.setDamage(damage);
		response.setOperCd(guardPlayerModule.getCoolDown().get(operate).getMillis());

		notificationGuard(guardModule);

		return Result.Success;
	}

	public Result operate(String playerCode, int operation, GuardMessage.GuardOperateResponse.Builder response) {
		GuardModule guardModule = GuardModule.get(playerCode);
		if (!guardModule.getState().equals(GuardState.GS_2_攻城)) {
			return Result.GuardCantOperate;// 不能做这个操作
		}
		GuardOperate operate = GuardOperate.forNumber(operation);
		GuardPlayerModule guardPlayerModule = GuardPlayerModule.get(playerCode);
		DateTime cd = guardPlayerModule.getCoolDown().get(operate);
		DateTime now = DateTime.now();
		boolean isGuard = guardModule.guard(playerCode);
		switch (operate) {
		case OP_医疗: {
			if (!isGuard || now.isBefore(cd)) {
				return Result.GuardCantOperate;// 不能做这个操作
			}
			Guard guard = guardModule.getGuards().get(guardModule.current());
			int add = GuardModule.data().getTreatmen();
			int cdtime = GuardModule.data().getTreatmentcd();
			guard.addHp(add);
			guardPlayerModule.getCoolDown().put(operate, now.plusSeconds(cdtime));

			guardModule.set();
			guardPlayerModule.set();

			notificationGuardSimple(guardModule);
		}
			break;
		case OP_急救: {
			if (!isGuard || now.isBefore(cd)) {
				return Result.GuardCantOperate;// 不能做这个操作
			}
			Guard guard = guardModule.getGuards().get(guardModule.current());
			int add = GuardModule.data().getRescue();
			int cdtime = GuardModule.data().getRescuecd();
			guard.addHp(add);
			guardPlayerModule.getCoolDown().put(operate, now.plusSeconds(cdtime));

			guardModule.set();
			guardPlayerModule.set();

			notificationGuardSimple(guardModule);
		}
			break;
		case OP_袭营: {
			if (!isGuard || now.isBefore(cd) || guardModule.inspireValue() <= 0) {
				return Result.GuardCantOperate;// 不能做这个操作
			}
			guardModule.raid(now);
			guardModule.set();

			int cdtime = GuardModule.data().getRaidcd();
			guardPlayerModule.getCoolDown().put(operate, now.plusSeconds(cdtime));
			guardPlayerModule.set();

			notificationGuardSimple(guardModule);
		}
			break;
		case OP_激励: {
			if (isGuard || now.isBefore(cd)) {
				return Result.GuardCantOperate;// 不能做这个操作
			}
			guardModule.inspire(now);
			guardModule.set();

			int cdtime = GuardModule.data().getInspirecd();
			guardPlayerModule.getCoolDown().put(operate, now.plusSeconds(cdtime));
			guardPlayerModule.set();

			notificationGuardSimple(guardModule);
		}
			break;
		case OP_攻城: {
			return Result.GuardCantOperate;// 不能做这个操作
		}
		default:
			break;

		}

		response.setOperation(operation);
		response.setOperCd(guardPlayerModule.getCoolDown().get(operate).getMillis());

		return Result.Success;
	}

	/** 领取洛阳宝藏 */
	public Result reward(String playerCode, GuardMessage.GuardRewardResponse.Builder response) {
		GuardModule guardModule = GuardModule.get(playerCode);

		GuardPlayerModule guardPlayerModule = GuardPlayerModule.get(playerCode);
		boolean isGuard = guardModule.guard(playerCode);
		GuardState state = guardModule.getState();

		boolean canReward = false;
		if (state.equals(GuardState.GS_3_守胜)) {
			canReward = isGuard && !guardPlayerModule.isRewarded();
		} else {
			canReward = !isGuard && !guardPlayerModule.isRewarded() && guardModule.isOffense(playerCode);
		}
		if (canReward) {
			Currencies rewards = reward(isGuard);
			new CurrencyHandle().addCurrency(playerCode, CCReason.洛阳守卫, rewards);
			response.addAllRewards(new CurrencyHandle().packItems(rewards));

			guardPlayerModule.setRewarded(true);
			guardPlayerModule.set();
			return Result.Success;
		}
		return Result.ParamError;
	}

	private Currencies reward(boolean isGuard) {
		if (isGuard) {
			packagedata data = DataCenter.getData(3002, packagedata.class);
			return new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
		}
		packagedata data = DataCenter.getData(3001, packagedata.class);
		return new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));

	}

	public Result clearAttackCd(String playerCode, Builder response) {
		GuardModule guardModule = GuardModule.get(playerCode);
		boolean isGuard = guardModule.guard(playerCode);
		if (!guardModule.getState().equals(GuardState.GS_2_攻城) || isGuard) {
			return Result.GuardCantOperate;// 不能做这个操作
		}
		GuardPlayerModule guardPlayerModule = GuardPlayerModule.get(playerCode);

		DateTime cd = guardPlayerModule.getCoolDown().get(GuardOperate.OP_攻城);
		DateTime now = DateTime.now();
		if (now.isAfter(cd)) {
			return Result.Success;
		}
		Currency cost = Currency.create(CurrencyType.CT_元宝, 0, GuardModule.data().getAssaultreset());
		try {
			new CurrencyHandle().cost(playerCode, CCReason.洛阳守卫, cost);
		} catch (CurrencyNotEnoughException e) {
			return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());// 献祭的碎片数量不足
		}
		guardPlayerModule.getCoolDown().put(GuardOperate.OP_攻城, now);
		guardPlayerModule.set();

		response.setOperCd(0);

		return Result.Success;
	}

	// 订阅==================================================================
	public void subscriber(String playerCode) {
		GuardSubscriber.get(playerCode).add(playerCode);
	}

	private GuardMessage.GuardStateInfo.Builder notificationInfo(GuardModule guardModule) {
		GuardMessage.GuardStateInfo.Builder stateInfo = GuardMessage.GuardStateInfo.newBuilder();
		int guardIndex = guardModule.current();
		for (Guard guard : guardModule.getGuards()) {
			GuardMessage.GuardInfo.Builder guardInfo = GuardMessage.GuardInfo.newBuilder();
			guardInfo.setAlive(guard.alive());
			stateInfo.addGuards(guardInfo);
		}
		Guard currentGuard = guardModule.getGuards().get(guardIndex);
		stateInfo.setBeing(guardIndex);
		stateInfo.setHp(currentGuard.hp());
		stateInfo.setInspire(guardModule.inspireValue());

		return stateInfo;
	}

	public void notificationGuardSimple(GuardModule guardModule) {
		GuardMessage.GuardStateInfo.Builder stateInfo = notificationInfo(guardModule);
		GuardMessage.GuardInfoNotification.Builder builder = GuardMessage.GuardInfoNotification.newBuilder();
		builder.setInfo(stateInfo);
		GuardMessage.GuardInfoNotification notify = builder.build();

		for (String playerCode : GuardSubscriber.get(guardModule.getAreaId()).clear()) {
			MessageEmitterHandler.getInstance().send(playerCode, notify);
		}
	}

	public void notificationGuard(GuardModule guardModule) {
		GuardMessage.GuardStateInfo.Builder stateInfo = notificationInfo(guardModule);

		// 伤害排名
		AreaBean areaBean = AreaBean.get(guardModule.getAreaId());
		RankGuard rankGuard = new RankGuard(areaBean, guardModule.current());

		Collection<RankEntry> attack = rankGuard.top(5);
		int rank = 0;
		for (RankEntry entry : attack) {
			GuardMessage.RankGuard.Builder rankbuilder = GuardMessage.RankGuard.newBuilder();
			rankbuilder.setRank(++rank);
			rankbuilder.setPlayerInfo(playerMiniInfo(entry.getKey()));
			rankbuilder.setDamage(entry.getValue());
			stateInfo.addRank(rankbuilder);
		}

		for (String playerCode : GuardSubscriber.get(guardModule.getAreaId()).clear()) {
			GuardMessage.GuardInfoNotification.Builder builder = GuardMessage.GuardInfoNotification.newBuilder();
			{
				int playerRank = 0;
				int score = 0;
				RankEntry entry = rankGuard.get(playerCode);
				if (entry != null) {
					playerRank = rankGuard.rank(playerCode);
					score = entry.getValue().intValue();
				}
				GuardMessage.RankGuard.Builder rankbuilder = GuardMessage.RankGuard.newBuilder();
				rankbuilder.setRank(playerRank);
				rankbuilder.setPlayerInfo(playerMiniInfo(playerCode));
				rankbuilder.setDamage(score);
				stateInfo.setMy(rankbuilder);
			}

			builder.setInfo(stateInfo);
			GuardMessage.GuardInfoNotification notify = builder.build();

			MessageEmitterHandler.getInstance().send(playerCode, notify);
		}
	}

	public PlayerMessage.PlayerSimpleInfo.Builder playerMiniInfo(String playerCode) {
		PlayerBean player = PlayerBean.get(playerCode);
		PlayerMessage.PlayerSimpleInfo.Builder builder = PlayerMessage.PlayerSimpleInfo.newBuilder();
		builder.setNickname(player.getName());
		builder.setHead(player.getHead());
		builder.setHeadFrame(player.getHeadframe());
		builder.setLevel(player.getLevel());
		return builder;
	}

	// future==========================================================
	public void update(AreaBean areaBean) {
		RedisLock lock = GuardModule.lock(areaBean.getAreaId());
		try {
			if (lock.tryLock()) {
				DateTime now = DateTime.now();
//		System.err.println("刷新洛阳守卫：" + now.toString());
				GuardModule guardModule = GuardModule.get(areaBean.getAreaId());
				DateTime stateTime = guardModule.getStateTimes().get(guardModule.getState());
				DateTime endtTime = guardModule.getStateTimes().get(GuardState.GS_3_守胜);
				// 活动结束
				if (now.isAfter(endtTime)) {
					guardModule.resetState(now);
					//如果连第一关都没打过，给参与的玩家发放安慰奖
					guardModule.sendComfortReward(areaBean);
					guardModule.set();
					return;
				}
				while (now.isAfter(stateTime)) {
					GuardState state = guardModule.getState().getNext();
					guardModule.updateState(state);

					stateTime = guardModule.getStateTimes().get(guardModule.getState());
				}
				guardModule.set();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

}
